import { _decorator, Component, Node, v3, CircleCollider2D, Vec2, Size, UITransform, Vec3, clamp } from 'cc';
import { GlobalConfig } from '../../Init/Config/GlobalConfig';
import { GlobalEnum } from '../../Init/Config/GlobalEnum';
import { GlobalTmpData } from '../../Init/Config/GlobalTmpData';
import EventManager from '../../Init/Managers/EventManager';
import { EventTypes } from '../../Init/Managers/EventTypes';
import { AudioEnum } from '../../Init/SystemAudio/AudioEnum';
import { AudioSystem } from '../../Init/SystemAudio/AudioSystem';
import { StorageSystem } from '../../Init/SystemStorage/StorageSystem';
import { BasicEnemy, EnemyAlive, EnemyDeath } from './BasicEnemy';
import { Zombie2D } from './Zombie2D';
const { ccclass, property } = _decorator;

@ccclass('Army2D')
export class Army2D extends BasicEnemy {

    public init(enemyName: string): void {
        super.init();
        this.mappingProps.enemyName = enemyName;
    }
    public setBodySize(s: Size) {
        let trans = this.node.getComponent(UITransform);
        trans.setContentSize(s);

        let body = this.node.getComponent(CircleCollider2D);
        if (body) {
            body.radius = s.width;
            body.apply();
        }
    }

    setHp() {
        let lv = StorageSystem.getData().levelAssets.curLv;
        let hp = GlobalConfig.People.BossHp;

        hp += Math.floor(lv / GlobalConfig.Enemy.hpStepLv) * GlobalConfig.Enemy.hpStep;
        hp = clamp(Math.floor(hp), GlobalConfig.People.BossHp, GlobalConfig.Enemy.hpMax);

        this.hp = hp;
        this.aimNum = hp;
        this.maxHp = hp;
        this.node[GlobalEnum.ExtralProp.customProps].hp = hp;
        this.node[GlobalEnum.ExtralProp.customProps].maxHp = hp;
    }

    /**设置初始状态 */
    protected setStateData() {
        this._stateRecs[GlobalEnum.EnemyState.Alive] = new ArmAlive(this);
        this._stateRecs[GlobalEnum.EnemyState.Death] = new ArmDeath(this);

        setTimeout(() => {
            this.changeState(GlobalEnum.EnemyState.Alive);
        }, 0);
    }
}

export class ArmAlive extends EnemyAlive {
    public atkDist: number = 0;
    public atkCd: number = 0;
    public atk: number = 0;
    //------旋转
    public _rotVec = v3();
    //目标弧度
    public _toRadianY = 0;
    //初始弧度
    public _curRadianY = -Math.PI * 0.5;
    //旋转方向 
    public _rotDirec = 1;
    //旋转速度
    public _rotSpd = Math.PI * 4;
    //
    private isShowEmoji = false;
    //子弹限制
    private _bulletMax = 0;
    private _bulletCount = 0;
    private _changeBulletCd = 0;
    private _changeBulletTime = 0;
    private _isChangeBullet = false;

    public enter(d?: any): void {
        super.enter(d);
        const _cfg = GlobalConfig.Army[this.cmp.mappingProps.enemyName];
        this.atkDist = _cfg.atkDist;
        this.atkCd = 1 / _cfg.atkSpd;
        this.atk = this.cmp.isBoss ? GlobalConfig.Enemy.ArmyBossAtk : _cfg.atk;

        //子弹
        this._bulletCount = this._bulletMax = _cfg.bulletNum;
        this._changeBulletCd = _cfg.bulletCd;
        this._changeBulletTime = 0;
        this._isChangeBullet = false;

        //攻击加成
        let lv = StorageSystem.getData().levelAssets.curLv;
        let atkLvRate = lv < 3 ? GlobalConfig.Enemy.guideLvRate : GlobalConfig.Enemy.atkLvRate;
        this.atk *= (1 + (lv - 1) * atkLvRate);

        //绑定数据
        this.cmp.node[GlobalEnum.ExtralProp.ArmyAtk] = false;

        //初始角度
        let curAng = v3(this.cmp.node.eulerAngles);
        this._toRadianY = curAng.y * 0.01745;
        this._curRadianY = this._toRadianY;
    }

    public update(dt: any): void {
        super.update(dt);
        this.rotation(dt);
        this.checkBullet(dt);
    }

    //#region ------子弹限制-------
    protected checkBullet(dt) {
        if (this._isChangeBullet) {
            this._changeBulletTime += dt;
            if (this._changeBulletTime >= this._changeBulletCd) {
                this._changeBulletTime = 0;
                this._bulletCount = this._bulletMax;
                this._isChangeBullet = false;
            }
        }
        this.cmp.node[GlobalEnum.ExtralProp.ArmyAtk] = this.isInArea && this._bulletCount > 0;
    }
    //#endregion

    public onChecked(zombie: Zombie2D) {
        //发射信息    
        this._shootRes.p.set(this.cmp.node.position);
        this._shootRes.direc.set(zombie.node.worldPosition).subtract(this.cmp.node.worldPosition);

        this.calRotation(Math.atan2(this._shootRes.direc.y, this._shootRes.direc.x));

        if (!this.isShowEmoji && !this.cmp.isBoss) {
            this.isShowEmoji = true;
            if (Math.random() < 0.5) {
                //表情
                EventManager.emit(EventTypes.EffectEvents.ShowEmoji,
                    { t: GlobalEnum.EmojiTypes.EnemyAngry, target: this.cmp.node });
            }
        }

        //
        let t = this.cmp.isBoss ? GlobalEnum.DialogTargetType.ArmyBoss : GlobalEnum.DialogTargetType.Army;
        EventManager.emit(EventTypes.RoleEvents.ShowDialog, t);
    }

    //旋转2d
    public rotation(dt) {
        if (this._curRadianY !== this._toRadianY) {
            let step = this._rotSpd * dt;
            if (step > Math.abs(this._curRadianY - this._toRadianY)) {
                this._curRadianY = this._toRadianY;
            } else {
                step *= this._rotDirec;
                this._curRadianY += step;
            }
            this._rotVec.set(0, 0, this._curRadianY * 57.3);
            this.cmp.node.eulerAngles = this._rotVec;
        }
    }
    private tmpP = v3();
    //发射子弹偏移
    private _shotOffset = v3(-0.3, 0, 0);
    public onAtk(): void {
        if (this._bulletCount <= 0) {
            this._bulletCount = 0;
            this._isChangeBullet = true;
            if (this.cmp.isBoss) {
                this._isChangeBullet = false;
                this._bulletCount = this._bulletMax;
            }

            if (!this.cmp.isBoss && this._changeBulletTime == 0) {
                //显示子弹cd
                this.tmpP.set(this.cmp.node.position.x * GlobalConfig.Scale2DTo3D, 0, -this.cmp.node.position.y * GlobalConfig.Scale2DTo3D);
                EventManager.emit(EventTypes.EnemyEvents.showArmyBulletCd, { uuid: this.cmp.node.uuid, p: this.tmpP, cd: this._changeBulletCd });
            }
            return;
        }
        this._bulletCount--;

        const cfg = GlobalConfig.Army[this.cmp.mappingProps.enemyName];
        this._shootRes.t = cfg.bulletType;
        this._shootRes.atk = this.atk;
        let s = this.cmp.isBoss ? GlobalConfig.Enemy.BossScale : 1;
        //子弹位置偏移        
        Vec3.rotateZ(this._shootRes.p, this._shotOffset, Vec3.ZERO, (this.cmp.node.eulerAngles.z + 90) * 0.01745);
        this._shootRes.p.multiplyScalar((1 / GlobalConfig.Scale2DTo3D) * s);
        this._shootRes.h = 0.85 * s;
        this._shootRes.p.add(this.cmp.node.position);
        //发射子弹
        EventManager.emit(EventTypes.EnemyEvents.ShootBullet, this._shootRes);
        //音效
        let audio = AudioEnum.shoot1;
        switch (this.cmp.mappingProps.enemyName) {
            case 'soldierA':
                audio = AudioEnum.shoot1;
                break;
            case 'soldierB':
                audio = AudioEnum.shoot2;
                break;
            case 'soldierC':
                audio = AudioEnum.shoot3;
                break;
            case 'soldierD':
                audio = AudioEnum.shoot4;
                break;
            default:
                break;
        }

        AudioSystem.playEffect(audio);
    }

    //根据目标旋转角度计算出旋转方式-弧度计算
    public calRotation(r: number) {
        this._toRadianY = r;
        //1.0 将当前角色角度+目标角度转换到360之内-弧度计算
        const pi = Math.PI;
        if (this._toRadianY < 0) {
            this._toRadianY += pi * 2;
        }
        this._curRadianY = this._curRadianY % (pi * 2);
        if (this._curRadianY > pi * 2) {
            this._toRadianY -= pi * 2;
        } else if (this._curRadianY < 0) {
            this._toRadianY += pi * 2;
        }
        //2.0 判断差值范围
        let sub = this._toRadianY - this._curRadianY;
        if (sub > pi) {
            //反向
            this._curRadianY += pi * 2;
            this._rotDirec = -1;
        } else if (sub < -pi) {
            //反向
            this._toRadianY += pi * 2;
            this._rotDirec = 1;
        } else if (sub > 0) {
            this._rotDirec = 1;
        } else if (sub < 0) {
            this._rotDirec = -1;
        }
    }
}

export class ArmDeath extends EnemyDeath {

    public enter(d) {
        super.enter(d);
        if (this.cmp.isBoss) {
            GlobalTmpData.Player.kill.boss++;
        }
    }

    tmpV3 = v3();
    protected onFinish() {
        super.onFinish();
        if (!this.cmp.isBoss) {
            //奖励
            this.tmpV3.set(this.cmp.node.position.x * GlobalConfig.Scale2DTo3D, 1, -this.cmp.node.position.y * GlobalConfig.Scale2DTo3D);
            let award = GlobalConfig.Award[this.cmp.mappingProps.enemyName] || 30;
            EventManager.emit(EventTypes.UIEvents.AddGoldEffect, { wpos: this.tmpV3, gold: award, isAnim: false });
        }
    }
}

